package org.xserver.disruptor.core;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.xserver.component.spring.SpringUtil;
import org.xserver.disruptor.annotation.EventConsumer;

import com.lmax.disruptor.EventHandler;
@Service
public class MessageEventFactoryProcessor {
    private final Logger logger = LoggerFactory.getLogger(MessageEventFactoryProcessor.class);

    public void registerEvent() {
    	ApplicationContext ctx = SpringUtil.getApplicationContext();
        DisruptorEventFactory disEventfactory = ctx.getBean(DisruptorEventFactory.class);
        if (null != disEventfactory) {
            Map<String, Object> objects =  ctx.getBeansWithAnnotation(EventConsumer.class);
            if (null != objects) {
                for (Object o : objects.values()) {
                    if (o instanceof EventHandler) {
                        Class eventType =getGenericType(o.getClass());
                        
                        if (null != eventType) {
                            disEventfactory.register(o, eventType);
                        } else {
                            logger.warn("Object:{} not a genericType.", o);
                        }
                    } else {
                        logger.warn("Object:{} not implement EventHandler.", o);
                    }
                }
            }
        } else {
            logger.warn("AsyncEventBus isn't configure...");
        }
    }
    
    private  Class getGenericType(Class type){
    	try {
    		Type[] ty = Class.forName(type.getCanonicalName()).getGenericInterfaces();
            if (null == ty || ty.length != 1) {
                return null;
            } else {
                Type[] params = ((ParameterizedType) ty[0]).getActualTypeArguments();
                int index = 0;
                if (index >= params.length || index < 0) {
                    throw new RuntimeException("Index outof bounds");
                }
                if (!(params[index] instanceof Class)) {
                    return Object.class;
                }
                return (Class) params[index];
            }
		
		} catch (Exception e) {
			logger.error("Get eventType error", e);
			return null;
		}
    	
    }
    
}
